/**
 * @file crop.h
 * @author Andreas Bok Andersen
 * @brief Header file for the implementation of Crop
 */

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <tr1/unordered_map>
#include <vector>
#include <iterator>
#include <algorithm>
#include "summary.h"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>

#include <boost/random/mersenne_twister.hpp>
#include "boost/random.hpp"
#include <boost/random/uniform_real.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/linear_congruential.hpp>

using namespace std;
using namespace tr1;
using namespace boost;

typedef boost::uniform_01<> NumberDistribution;
typedef boost::mt19937 RandomNumberGenerator;
typedef boost::variate_generator<RandomNumberGenerator&, NumberDistribution> RandGenerator;

typedef unordered_map<unsigned int, unsigned> INT_INT_MAP;
typedef vector<float> FLOAT_VEC;

#ifndef COO_ITEM
struct COO_item {
	COO_item() {
	}
	;
	COO_item(int _i, int _j, float _w) :
			i(_i), j(_j), w(_w) {
	}
	;
	int i, j;
	float w;
};
#define COO_ITEM
#endif

#ifndef DCS_ITEM
typedef struct {
	int i;
	float w;
} DCS_item;
#define DCS_ITEM
#endif

#ifndef COOFORMAT
	struct COO_FORMAT {};
#define COOFORMAT
#endif

#ifndef DCSFORMAT
	struct DCS_FORMAT {};
	#define DCSFORMAT
#endif

struct CropItem {
	int hash, idx;
	float val;

	CropItem(int _hash, int _idx, float _val) {
		hash = _hash;
		idx = _idx;
		val = _val;
	}

	~CropItem() {
	}
};

bool compare(const CropItem& x, const CropItem& y) {
	return x.hash < y.hash;
}

typedef vector<CropItem> CROPITEM_VEC;

RandomNumberGenerator generator;
NumberDistribution distribution;
RandGenerator numberGenerator(generator, distribution);

template<class T>
class Crop {
private:
	int p, rank, size;
	T * summary;
	CROPITEM_VEC *h1val, *h2val;
	unsigned int val(unsigned int x, INT_INT_MAP *h, int bit);
	void do_product(CROPITEM_VEC *col, CROPITEM_VEC *row, int count[]);
	Crop(int rank, int comm_size);

public:
	INT_INT_MAP *h1, *h2;
	Crop(int rank, int comm_size, int k);
	~Crop();
	void crop(int * IR, float * NUM, int nnz);
	void crop(int * IR, float * NUM, int nnz, COO_FORMAT);
	void crop(int * IR, float * NUM, int nnz, DCS_FORMAT);

	ENTRY_VEC get_summary();
	void get_summary(Entry * entries);
	void get_summary(ENTRY_VEC *entries);
	int summarysize();
	string to_string();
	int * pdist;
};

#include "crop.cpp"
